﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace DeMountCIM.Framework.RFID
{
    public class DTE104Client
    {
        TcpClient client;
        NetworkStream clientStream;

        //declare separator to parse answer strings
        char[] delimiterChars = { '_', '\r', '\n' };

        public bool Connect(string ip, int port)
        {
            try
            {
                if (client != null)
                {
                    client.Close();
                    client = null;
                }

                client = new TcpClient();
                client.Connect(IPAddress.Parse(ip), port);
                return true;
            }
            catch
            {
                Trace.WriteLine("No connetion", "Error");
                return false;
            }
        }

        public void DisConnect()
        {
            if (clientStream != null)
            {
                clientStream.Close();
                clientStream.Dispose();
                clientStream = null;
            }
            if (client != null)
            {
                client.Close();
                client = null;
            }
        }

        public bool IsConnected()
        {
            if (client == null)
            {
                return false;
            }

            return client.Connected;
        }

        // 获取UID
        public string GetUID(int ioPort)
        {
            if (!IsConnected())
            {
                return "";
            }
            ReadUID(ioPort, out string uid);
            return uid;
        }

        // 获取晶托编号
        public bool ReadCarrierID(int ioPort, out string dataOrError)
        {
            if (!IsConnected())
            {
                dataOrError = "";
                return false;
            }

            return ReadRFIDData(ioPort, "00000", "0016", out dataOrError);
        }

        // 获取RFID芯片中的所有数据
        public bool GetRFIDTagData(int ioPort, out string dataOrError)
        {
            if (!IsConnected())
            {
                dataOrError = "";
                return false;
            }

            return ReadRFIDData(ioPort, "00000", "0200", out dataOrError);
        }

        // 写入数据
        public bool WriteRfidTagData(int ioPort, int startAddress, int length, string data, out string error)
        {
            int i1 = 5, i2 = 4;

            string strAddress = startAddress.ToString();
            string strLength = length.ToString();
            if (strAddress.Length > i1 || strLength.Length > i2)
            {
                error = "参数错误！";
                return false;
            }
            var count = i1 - strAddress.Length;
            for (int i = 0; i < count; i++)
            {
                strAddress = "0" + strAddress;
            }
            count = i2 - strLength.Length;
            for (int i = 0; i < count; i++)
            {
                strLength = "0" + strLength;
            }

            if (!IsConnected())
            {
                error = "";
                return false;
            }

            return WriteRFIDData(ioPort, strAddress, strLength, data, out error);
        }

        #region 内部方法

        // 读取UID
        private bool ReadUID(int ioPort, out string uid)
        {
            try
            {
                string data_dte104 = SendMessage($"RU_0{ioPort}\r\n");
                string[] split_data = data_dte104.Split(delimiterChars);
                uid = split_data[4];
                return true;
            }
            catch (Exception ex)
            {
                uid = "00000";
                return false;
            }
        }

        /// <summary>
        /// 读取RFID数据
        /// </summary>
        /// <param name="startAddress">
        /// 起始位
        /// 5位数
        /// 00000
        /// </param>
        /// <param name="length">
        /// 长度
        /// 4位数
        /// 0000
        /// </param>
        /// <param name="dataOrError">
        /// 成功为数据，不成功为错误
        /// </param>
        /// <returns></returns>
        private bool ReadRFIDData(int ioPort, string startAddress, string length, out string dataOrError)
        {
            try
            {
                string cmmid = $"RD_0{ioPort}_" + startAddress + "_" + length + "\r\n";

                string data_dte104 = SendMessage(cmmid);
                string[] split_data = data_dte104.Split(delimiterChars);

                string error_dte104 = split_data[2];

                //check if a diagnosis event happen
                if (error_dte104 == "01")
                {
                    //read out diagnosis if error happen
                    data_dte104 = SendMessage($"DI_0{ioPort}\r\n");
                    split_data = data_dte104.Split(delimiterChars);

                    dataOrError = split_data[4];

                    return false;
                }
                else
                {
                    dataOrError = split_data[5];
                    return true;
                }
            }
            catch (Exception ex)
            {
                dataOrError = "网络错误";
                return false;
            }

        }

        /// <summary>
        /// 写入RFID数据
        /// </summary>
        /// <param name="startAddress">
        /// 起始位
        /// 5位数
        /// 00000
        /// </param>
        /// <param name="length">
        /// 长度
        /// 4位数
        /// 0000
        /// </param>
        /// <param name="requsetData">
        /// 写入的数据
        /// </param>
        /// <param name="error">
        /// 错误信息
        /// </param>
        /// <returns></returns>
        private bool WriteRFIDData(int ioPort, string startAddress, string length, string requsetData, out string error)
        {
            string data_dte104 = SendMessage($"WR_0{ioPort}_" + startAddress + "_" + length + "_" + requsetData.PadRight(Int32.Parse(length), '-') + "\r\n");
            string[] split_data = data_dte104.Split(delimiterChars);

            string error_dte104 = split_data[2];

            //check if a diagnosis event happen
            if (error_dte104 == "01")
            {
                //read out diagnosis if error happen
                data_dte104 = SendMessage($"DI_0{ioPort}\r\n");
                split_data = data_dte104.Split(delimiterChars);

                error = split_data[4];
                return false;
            }
            else
            {
                error = null;
                return true;
            }
        }

        private void RFIDRestart()
        {
            string commid = "DI_03";

        }

        /// <summary>
        /// 发送数据给RFID
        /// </summary>
        /// <param name="msg"></param>
        /// <returns>
        /// 获取接收到的数据
        /// </returns>
        private String SendMessage(string msg)
        {
            try
            {

                //NetworkStream 
                clientStream = client.GetStream();

                ASCIIEncoding encoder = new ASCIIEncoding();
                byte[] buffer = encoder.GetBytes(msg);

                clientStream.Write(buffer, 0, buffer.Length);
                clientStream.Flush();

                // Receive the TcpServer.response. 

                // Buffer to store the response bytes. 
                Byte[] data = new Byte[2048];

                // String to store the response ASCII representation. 
                String responseData = String.Empty;

                // Read the first batch of the TcpServer response bytes. 
                Int32 bytes = clientStream.Read(data, 0, data.Length);
                responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);

                return responseData;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                return null;
            }
        }

        #endregion

    }
}
